package com.jameskarl.amap.map.bean

import android.graphics.Point
import android.location.Location
import com.amap.api.location.AMapLocation
import com.amap.api.maps.AMapOptions
import com.amap.api.maps.model.*
import com.autonavi.amap.mapcore.Inner_3dMap_location
import com.jameskarl.amap.map.IJsonEntity

data class LatLngData(
        var latitude: Double = 0.0,
        var longitude: Double = 0.0,
        var name: String? = null
) : IJsonEntity {

    constructor(position: LatLng) : this(position.latitude, position.longitude)

    constructor(args: Map<*, *>) : this(
            latitude = args["latitude"] as Double,
            longitude = args["longitude"] as Double,
            name = args["name"] as String?)

    fun toLatLng() = LatLng(latitude, longitude, true)

    override fun toString(): String {
        return "LatLngData(latitude=$latitude, longitude=$longitude)"
    }
}

data class ScreenPoint(var x: Int = 0, var y: Int = 0) : IJsonEntity {

    fun toPoint() = Point(x, y)

    override fun toString(): String {
        return "ScreenPoint(x=$x, y=$y)"
    }
}

data class LatLngBoundsData(
        var northeast: LatLngData = LatLngData(),
        var southwest: LatLngData = LatLngData()
) : IJsonEntity {
    fun toLatLngBounds(): LatLngBounds {
        return LatLngBounds(southwest.toLatLng(), northeast.toLatLng())
    }

    override fun toString(): String {
        return "LatLngBoundsData(northeast=$northeast, southwest=$southwest)"
    }
}

data class CameraPositionData(
        var bearing: Double? = null,
        var target: LatLngData? = null,
        var tilt: Double? = null,
        var minZoom: Double? = null,
        var maxZoom: Double? = null,
        var zoom: Double? = null
) : IJsonEntity {

    constructor(cameraPosition: CameraPosition) : this(
            bearing = cameraPosition.bearing.toDouble(),
            target = LatLngData(cameraPosition.target),
            tilt = cameraPosition.tilt.toDouble(),
            zoom = cameraPosition.zoom.toDouble()
    )

    fun toCameraPosition(): CameraPosition {
        val builder = CameraPosition.Builder()
        bearing?.let { builder.bearing(it.toFloat()) }
        target?.let { builder.target(it.toLatLng()) }
        tilt?.let { builder.tilt(it.toFloat()) }
        zoom?.let { builder.zoom(it.toFloat()) }
        return builder.build()
    }

    fun valid() = target != null

    override fun toString(): String {
        return "CameraPositionData(bearing=$bearing, target=$target, tilt=$tilt, zoom=$zoom)"
    }
}

data class UiSettings(
        var logoPosition: Int? = null,
        var zoomPosition: Int? = null,
        var compassEnabled: Boolean? = null,
        var gestureScaleByMapCenter: Boolean? = null,
        var indoorSwitchEnabled: Boolean? = null,
        var myLocationEnabled: Boolean? = null,
        var myLocationButtonEnabled: Boolean? = null,
        var rotateGesturesEnabled: Boolean? = null,
        var scaleControlsEnabled: Boolean? = null,
        var scrollGesturesEnabled: Boolean? = null,
        var tiltGesturesEnabled: Boolean? = null,
        var zoomControlsEnabled: Boolean? = null,
        var zoomGesturesEnabled: Boolean? = null,
        var allGesturesEnabled: Boolean? = null
) : IJsonEntity {
    fun getAMapLogoPosition(): Int? = when (logoPosition) {
        0 -> AMapOptions.LOGO_POSITION_BOTTOM_LEFT
        1 -> AMapOptions.LOGO_POSITION_BOTTOM_CENTER
        2 -> AMapOptions.LOGO_POSITION_BOTTOM_RIGHT
        else -> null
    }

    fun getAMapZoomPosition(): Int? = when (zoomPosition) {
        0 -> AMapOptions.ZOOM_POSITION_RIGHT_CENTER
        1 -> AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM
        else -> null
    }
}

data class MyLocationStyleData(
        var myLocationType: Long? = null,
        var radiusFillColor: Long? = null,
        var strokeColor: Long? = null,
        var strokeWidth: Float? = null,
        var interval: Long? = null,
        var myLocationIcon: String? = null
) : IJsonEntity {
    fun getAMapMyLocationType(): Int? =
            if (myLocationType != null)
                allMyLocationType[myLocationType!!.toInt()]
            else null
}

val allMyLocationType = listOf(
        MyLocationStyle.LOCATION_TYPE_SHOW,
        MyLocationStyle.LOCATION_TYPE_LOCATE,
        MyLocationStyle.LOCATION_TYPE_FOLLOW,
        MyLocationStyle.LOCATION_TYPE_MAP_ROTATE,
        MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE,
        MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER,
        MyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER,
        MyLocationStyle.LOCATION_TYPE_MAP_ROTATE_NO_CENTER
)

data class MapLocation(
        var latitude: Double? = null, // 30.506518
        var longitude: Double? = null, // 114.379487
        var province: String? = null, // 湖北省
        var city: String? = null, // 武汉市
        var district: String? = null, // 洪山区
        var cityCode: String? = null, // 027
        var adCode: String? = null, // 420111
        var address: String? = null, // 湖北省武汉市洪山区虎泉街靠近中国邮政储蓄银行(吴家湾营业所)
        var country: String? = null, // 中国
        var road: String? = null, // 虎泉街
        var poiName: String? = null, // 中国邮政储蓄银行(吴家湾营业所)
        var street: String? = null, // 虎泉街
        var streetNum: String? = null, // =265号
        var aoiName: String? = null, // =五环天地
        var floor: String? = null,
        var errorCode: Long? = null,
        var errorInfo: String? = null,
        var locationType: Long? = null
) : IJsonEntity

fun AMapLocation.toMapLocation(): MapLocation {
    return MapLocation(
            latitude = latitude,
            longitude = longitude,
            province = province,
            city = city,
            district = district,
            cityCode = cityCode,
            adCode = adCode,
            address = address,
            country = country,
            road = road,
            poiName = poiName,
            street = street,
            streetNum = streetNum,
            aoiName = aoiName,
            floor = floor,
            errorCode = errorCode.toLong(),
            errorInfo = errorInfo,
            locationType = locationType.toLong()
    )
}

fun Inner_3dMap_location.toMapLocation(): MapLocation {
    return MapLocation(
            latitude = latitude,
            longitude = longitude,
            province = province,
            city = city,
            district = district,
            cityCode = cityCode,
            adCode = adCode,
            address = address,
            country = country,
            road = road,
            poiName = poiName,
            street = street,
            streetNum = streetNum,
            aoiName = aoiName,
            floor = floor,
            errorCode = errorCode.toLong(),
            errorInfo = errorInfo,
            locationType = locationType.toLong()
    )
}

fun Location.toMapLocation(): MapLocation {
    return MapLocation(latitude = latitude, longitude = longitude)
}

fun VisibleRegion.toMap(): Map<String, Any> {
    return mapOf(
            "farLeft" to farLeft.toMap(),
            "farRight" to farRight.toMap(),
            "nearLeft" to nearLeft.toMap(),
            "nearRight" to nearRight.toMap(),
            "latLngBounds" to latLngBounds.toMap()
    )
}

fun LatLng.toMap(): Map<String, Double> {
    return mapOf("latitude" to latitude, "longitude" to longitude)
}

fun LatLngBounds.toMap(): Map<String, Any> {
    return mapOf(
            "northeast" to this.northeast.toMap(),
            "southwest" to this.southwest.toMap()
    )
}
